package com.eagle.functioninterface;

import org.junit.Assert;
import org.junit.Test;

import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;

/**
 * {@link java.util.function.Function} 这个函数式接口 就是把一个事物转成另一个事物
 * 其类似与数学中的y=f(x)
 * lambda 表达式是 x -> y
 *
 * @author qinlinsen
 */
public class FunctionTest4 {
    @Test
    public void testFunction() {
        //y=x + 3 当 x=3 时的值
        Integer resultOne = computation(3, x -> x + 3);
        System.out.println(String.format("resultOne=%s", resultOne));

        //计算y= 4 * x 当 x=5时的值：
        Integer resultTwo = computation(5, x -> 4 * x);
        System.out.println(String.format("resultTwo=%s", resultTwo));

        //计算 y = 10 / x 当 x=2的值：
        Integer resultThree = computation(2, x -> 10 / x);
        System.out.println(String.format("resultThree=%s", resultThree));
    }


    /**
     * 测试符合函数的用法
     */
    @Test
    public void testCompose() {
        //计算y=f(g(x)) 其中g(x)=3 * x ;   f(x) = 5 +x
        Function<Integer, Integer> g = x -> 3 * x;
        Function<Integer, Integer> f = x -> 5 + x;
        // 5+(3 * 3) =14
        Integer result = f.compose(g).apply(3);
        System.out.println(result);
        Assert.assertEquals(Optional.of(14).get(), result);
    }


    @Test
    public void testAndThen() {
        //计算y=f(g(x)) 其中g(x)=3 * x ;   f(x) = 5 +x
        Function<Integer, Integer> g = x -> 3 * x;
        Function<Integer, Integer> f = x -> 5 + x;
        //g(f(x)) = 3 * (5 + 3) =24
        Integer result = f.andThen(g).apply(3);
        System.out.println(String.format("result=%s", result));

        //从这里可以看出g.andThen(f).apply(x)=f.compose(g).apply(x)
        Assert.assertEquals(g.andThen(f).apply(3), f.compose(g).apply(3));
    }


    @Test
    public void testIdentity(){
        Object result = Function.identity().apply(3);
        //Function.identity得到的是:以什么数传进去，就以什么数传出去。
        Object helloWorld = Function.identity().apply("hello world");
        System.out.println(result);
        System.out.println(String.format("helloWorld=%s",helloWorld));
    }


    /**
     * @param independentVariable 自变量 x
     * @param compute             表达式 y=f(x)
     * @return
     */
    private static Integer computation(Integer independentVariable, Function<Integer, Integer> compute) {
        Objects.requireNonNull(compute);
        Integer result = compute.apply(independentVariable);
        return result;
    }

}
